﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;

namespace test
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        class CRC32Cls
        {
            protected ulong[] Crc32Table;         //生成CRC32码表   
      
            public void GetCRC32Table()
            {
                ulong Crc;
                Crc32Table = new ulong[256];

                for (int i = 0; i < 256; i++)
                {
                    Crc = (ulong)i;

                    for (int j = 8; j > 0; j--)
                    {
                        if ((Crc & 1) == 1)
                            Crc = (Crc >> 1) ^ 0xEDB88320;
                        else
                            Crc >>= 1;
                    }

                    Crc32Table[i] = Crc;
                }
            }

            public ulong GetCRC32Str(byte[] src_data) //获取字符串的CRC32校验值   
            {
                GetCRC32Table();  //生成码表 
                //byte[] buffer = System.Text.ASCIIEncoding.ASCII.GetBytes(sInputString);
                ulong value = 0xffffffff;
                //int len = buffer.Length;

                for (int i = 0; i < src_data.Length; i++)
                {
                    value = (value >> 8) ^ Crc32Table[(value & 0xFF) ^ src_data[i]];
                }

                return value ^ 0xffffffff;
            }
        }

        static UInt16 calc_crc16(Byte src_data, UInt16 crc16)
        {
            int i;
            UInt16 ret = crc16;

            for (i = 0x80; i != 0; i = i >> 1)               // 一个字节8位，故循环8次        
            {
                if ((ret & 0x8000) != 0)      // 高位为1则进行位或运算             
                {
                    ret <<= 1;             // 高位肯定为1，无需运算                 
                    ret ^= 0x1021;         // 与生成多项式异或              
                }
                else
                    ret <<= 1;             // 高位不为1，则乘2              
                if ((src_data & i) != 0)
                    ret ^= 0x1021;         // 加上本位的CRC码         
            }

            return ret;
        }

        static string get_file_info(string src_file_name, Byte[] file_content)
        {
            string ret_str;
            CRC32Cls CRC = new CRC32Cls();

            FileInfo src_file = new FileInfo(src_file_name);

            ret_str =  "   文 件 名 : " + src_file.Name + "\r\n\r\n";
            ret_str += "   路    径 : " + Path.GetDirectoryName(src_file_name) + "\r\n\r\n";
            ret_str += "   大    小 : " + src_file.Length / 1024 + " KB" + "\r\n\r\n";
            ret_str += "   修改日期 : " + src_file.LastWriteTime + "\r\n\r\n";
            ret_str += "   CRC32校验: " + String.Format("{0:X8}", CRC.GetCRC32Str(file_content));

            return ret_str;
        }

        static string change_file_fmt(string src_file_name)
        {
            string ret_str;

            /************************读二进制原文件*************************/
            FileStream fs = new FileStream(src_file_name, FileMode.Open, FileAccess.Read);
            BinaryReader br = new BinaryReader(fs);
            br.BaseStream.Seek(0, SeekOrigin.Begin);

            Byte[] b_tmp = new Byte[br.BaseStream.Length];
            br.Read(b_tmp, 0, (int)br.BaseStream.Length);
            br.Close();
            fs.Close();

            ret_str = "   /**************** 源文件信息 ****************/\r\n\r\n";
            ret_str += get_file_info(src_file_name, b_tmp);

            if (src_file_name.IndexOf(".bin") <= -1)
            {
                MessageBox.Show("源文件格式错误!");
                return ret_str;
            }

            /***********************创建优盘升级文件.csg**********************/
            string def_csg_fmt = "CSGUPDATEFILE";
            string csg_file = Path.GetDirectoryName(src_file_name) + "\\STM32USB.CSG";

            FileStream myCsg = new FileStream(csg_file, FileMode.Create);
            BinaryWriter myCsg_w = new BinaryWriter(myCsg);
            myCsg_w.Write(def_csg_fmt.ToArray());

            Byte[] tmp = new Byte[1];
            tmp[0] = 0xA0;
            myCsg_w.Write(tmp);

            myCsg_w.Write(b_tmp);
            myCsg_w.Close();
            myCsg.Close();

            Byte[] csg_crc32 = new Byte[def_csg_fmt.ToArray().Length + 1 + b_tmp.Length];
            (System.Text.Encoding.Default.GetBytes(def_csg_fmt)).CopyTo(csg_crc32, 0);
            tmp.CopyTo(csg_crc32, def_csg_fmt.ToArray().Length);
            b_tmp.CopyTo(csg_crc32, def_csg_fmt.ToArray().Length + 1);

            ret_str += "\r\n\r\n\r\n   /**************** 优盘文件信息 ****************/\r\n\r\n";
            ret_str += get_file_info(csg_file, csg_crc32);

            /***********************创建远程升级文件.txt**********************/
            string stm32_file = Path.GetDirectoryName(src_file_name) + "\\STM32_UP.txt";

            FileStream myStm32 = new FileStream(stm32_file, FileMode.OpenOrCreate, FileAccess.ReadWrite);
            StreamWriter myStm32_w = new StreamWriter(myStm32);

            myStm32_w.Write("@5000\r\n");

            byte i = 0;
            UInt16 tmp_crc16 = 0;

            foreach (Byte data in b_tmp)
            {
                i++;
                if (i % 16 == 0)
                {
                    i = 0;
                    myStm32_w.Write(data.ToString("X2") + "\r\n");
                }
                else
                {
                    myStm32_w.Write(data.ToString("X2") + " ");
                }

                tmp_crc16 = tmp_crc16 = calc_crc16(data, tmp_crc16);
            }
            myStm32_w.Flush();
            myStm32_w.Close();
            myStm32.Close();

            FileStream myStm32_2 = new FileStream(stm32_file, FileMode.Open);
            Byte[] r_buf = new byte[myStm32_2.Length];
            myStm32_2.Read(r_buf, 0, (int)myStm32_2.Length);
            myStm32_2.Close();

            ret_str += "\r\n\r\n\r\n   /**************** 远程文件信息 ****************/\r\n\r\n";
            ret_str += get_file_info(stm32_file, r_buf);


            /***********************创建文件传输.GUP**********************/
            string def_gup_fmt = "CSG\0UPDATEFILE\00000";
            Byte[] def_gup_date = {0x00, 0x00, 0x00, 0x00}; 

            string gup_file = Path.GetDirectoryName(src_file_name) + "\\STM32Term.GUP";

            FileStream myGup = new FileStream(gup_file, FileMode.Create);
            BinaryWriter myGup_w = new BinaryWriter(myGup);

            myGup_w.Write(def_gup_fmt.ToArray());

            myGup_w.Write(def_gup_date);

            Byte[] crc16 = new byte[2];
            crc16[0] = (Byte)(tmp_crc16 & 0x00ff);
            crc16[1] = (Byte)(tmp_crc16 >> 8);
            myGup_w.Write(crc16);
    
            myGup_w.Write(b_tmp);

            myGup_w.Close();
            myGup.Close();

            Byte[] gup_crc32 = new Byte[def_gup_fmt.ToArray().Length + 6 + b_tmp.Length];

            (System.Text.Encoding.Default.GetBytes(def_gup_fmt)).CopyTo(gup_crc32, 0);
            crc16.CopyTo(gup_crc32, def_gup_fmt.ToArray().Length + 4);
            b_tmp.CopyTo(gup_crc32, def_gup_fmt.ToArray().Length + 6);

            ret_str += "\r\n\r\n\r\n   /**************** 传输文件信息 ****************/\r\n\r\n";
            ret_str += get_file_info(gup_file, gup_crc32);

            return ret_str;
        }

        private void select_src_file_Click(object sender, EventArgs e)
        {
            OpenFileDialog file = new OpenFileDialog();
            file.Filter = "二进制文件(.bin)|*.bin";

            if (file.ShowDialog() == DialogResult.OK)
            {
                textBox.Text = change_file_fmt(file.FileName);
            }
        }

        private void textBox1_DragDrop_1(object sender, DragEventArgs e)
        {
            string file_name = ((System.Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString();

            textBox.Text = change_file_fmt(file_name);
        }

        private void textBox1_DragEnter_1(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
                e.Effect = DragDropEffects.Link;
            else
                e.Effect = DragDropEffects.None;
        }

        private void clear_display_Click(object sender, EventArgs e)
        {
            textBox.Text = "\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n                  请 将 .bin 文 件 拖 拽 在 这 里";
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            string[] vCommandLineArgs = Environment.GetCommandLineArgs();

            if (vCommandLineArgs.Length > 1)
            {
                    string vFileName = vCommandLineArgs[1];

                    if (File.Exists(vFileName))
                    {
                        textBox.Text = change_file_fmt(vFileName);
                    }
            }
        }
    }
}
